package java01_type;

import org.junit.jupiter.api.Test;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;

/**
 * [1]在使用BigDecimal类型进行计算时，进行加、减、乘、除、比较大小时，
 * 一定要保证参与计算的两个值不能为空，
 * 否则会抛出java.lang.NullPointerException异常。
 *
 * [2]不要用==或者equals比较BigDecimal的值，equals方法，其实不只是会比较数字的值，还会对其标度进行比较，是极其严格的。
 * 尤其当用字符串转BigDecimal对象后，千万不要用equals，容易有坑。所以最好用compareTo方法。
 *
 */
public class Test05_BigDecimal {

    /**
     * 两个BigDecimal对象进行相加，返回新的一个BigDecimal对象，原来加数的值不变。
     */
    @Test
    public void testAdd() {
        BigDecimal a = new BigDecimal("1.44444");
        BigDecimal b = new BigDecimal("1.33333");
        System.out.println(a.add(b));
        System.out.println(a);
        System.out.println(b);
    }

    @Test
    public void testReduce() {
        List<BigDecimal> nums = new LinkedList<>();
        nums.add(new BigDecimal(-1));
        nums.add(new BigDecimal(-1));
        nums.add(new BigDecimal(-3));

        Optional<BigDecimal> addResult = nums.stream().reduce(BigDecimal::add);
        System.out.println(addResult.get()); //-5

        BigDecimal sum = nums.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        System.out.println(sum);

        BigDecimal max = nums.stream().reduce(nums.get(0), BigDecimal::max);
        System.out.println(max); //-1

        BigDecimal min = nums.stream().reduce(nums.get(0), BigDecimal::min);
        System.out.println(min); //-3
    }

    /**
     * 减法
     */
    @Test
    public void testSubtract() {
        BigDecimal a = new BigDecimal("1.44444");
        BigDecimal b = new BigDecimal("1.33333");
        System.out.println(a.subtract(b));
        System.out.println(a);
        System.out.println(b);
    }

    /**
     * 乘法
     */
    @Test
    public void testMultiply() {
        BigDecimal a = new BigDecimal("1.44444");
        BigDecimal b = new BigDecimal("1.0");
        System.out.println(a.multiply(b));

        //设置小数点为3位
        System.out.println(a.multiply(b).setScale(3, RoundingMode.HALF_UP));

        //设置精度为3位
        System.out.println(a.multiply(b, new MathContext(3, RoundingMode.HALF_UP)));
    }

    /**
     * 除法
     */
    @Test
    public void testDivide() {
        BigDecimal a = new BigDecimal("1.44444");
        BigDecimal b = new BigDecimal("1.0");
        System.out.println(a.divide(b, 3, RoundingMode.HALF_UP));
    }

    /**
     * 取整
     */
    @Test
    public void testDivideToIntegralValue() {
        BigDecimal a = new BigDecimal("100.99999");
        BigDecimal b = new BigDecimal("5");
        System.out.println(a.divideToIntegralValue(b));
        System.out.println(a.divideToIntegralValue(b, new MathContext(4)));
    }

    /**
     * 取余
     */
    @Test
    public void testRemainder() {
        BigDecimal a = new BigDecimal("100.1112");
        BigDecimal b = new BigDecimal("33");
        System.out.println(a.remainder(b));
    }

    /**
     * BigDecimal的equals方法，其实不只是会比较数字的值，还会对其标度进行比较，是极其严格的。
     * BigDecimal的compareTo方法，只比较值，其中返回结果：-1表示小于，0表示等于，1表示大于。
     */
    @Test
    public void testCompare() {
        BigDecimal a = new BigDecimal("-1.00");
        BigDecimal b = new BigDecimal("-1.0");
        BigDecimal c = new BigDecimal("-3");
        System.out.println(a.compareTo(b)); //0
        System.out.println(c.compareTo(b)); //-1
        System.out.println(b.compareTo(c)); //1
        System.out.println(a.equals(b)); //false，equals是极其严格的
    }

    @Test
    public void testFormat() {
        BigDecimal a = new BigDecimal("5.55555555");
        BigDecimal b = new BigDecimal("0.55555555");
        BigDecimal c = new BigDecimal("0.05555555");

        NumberFormat percent = NumberFormat.getPercentInstance();  //建立百分比格式化引用
        percent.setMaximumFractionDigits(3); //百分比小数点【最多】3位

        System.out.println("a利率:\t" + percent.format(a));
        System.out.println("b利率:\t" + percent.format(b));
        System.out.println("c利率:\t" + percent.format(c));
    }

    @Test
    public void testScale() {
        BigDecimal a = new BigDecimal("1001.2345654157");
        System.out.println(a.setScale(3, RoundingMode.HALF_UP));
        System.out.println(a.setScale(3, RoundingMode.HALF_DOWN));
        System.out.println(a);
    }
}
